﻿Imports System
Imports System.Threading
Imports System.Collections.Generic

Imports NoDeadLockReadWriteLocker
Imports ThreadSafeClasses

Module ProgramMain
  Sub Main()
		InitalizeThreads()
  End Sub

	Dim Lock   As New ReadWriteLocker(ReadWriteLocker.Behavior.AllowDeadLocks)
	Dim List   As New List(Of Integer)(New Integer() {0,5,0,4,0,3,0,2,0,1})
	Dim IsBusy As Integer = 0

	Dim Lock1   As New ReadWriteLocker(ReadWriteLocker.Behavior.AllowDeadLocks)
	Dim List1   As New List(Of Integer)(New Integer() {0,5,0,4,0,3,0,2,0,1})
	Dim IsBusy1 As Integer = 0

  Dim List2   As New ThreadSafeList(Of Integer)(New Integer() {3,0,1}, True)

	Public Sub InitalizeThreads()
		For Index As Integer = 0 To 25
			Interlocked.Increment(IsBusy)
			ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf FunctionToRunInMultipleThreads), Index)
			ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf FunctionToRunInMultipleThreads1), Index)
		Next

		While IsBusy > 0
			Thread.Sleep(500)
		End While

		Console.WriteLine()
		Console.WriteLine("The last List seen should have numbers which match the last List1.")
		Console.WriteLine()
		Console.WriteLine("Finished! Press any key too continue...")
		Console.ReadLine()
	End Sub

	Public Sub FunctionToRunInMultipleThreads(threadContext As Object)
		Dim threadIndex As Integer = CInt(threadContext)
		Console.WriteLine("thread {0} started...", threadIndex)

		Using ReadLock As IDisposable = Lock.GetReadLock()
			' Iterate through list
			For Index As Integer = 0 To List.Count - 1
				List(Index) += Index
			Next

			' Upgrade read lock to write lock.  Yes.  It is that simple.
			Using WriteLock As IDisposable = Lock.GetWriteLock()
				For Index As Integer = 0 To List.Count - 1
					List.Add(List(Index))
				Next
			End Using
		End Using

		Using WriteLock As IDisposable = Lock.GetWriteLock()
			' Read lock not needed.  But it shows locking in this order is OK.
			Using ReadLock As IDisposable = Lock.GetReadLock()
				' Remove all but the first 10 records.
				List.RemoveRange(10, List.Count - 10)

				' Iterate through list
				For Index As Integer = 0 To List.Count - 1
					Console.WriteLine("List value {2}: {0}, on thread {1}.", List(Index), threadIndex, Index)
				Next
			End Using
		End Using

		Dim ItemIndex As Integer = 0

    For Each Item As Integer In List2
			List2(ItemIndex) = List2(ItemIndex) + 1

			Console.WriteLine("List2 #1 value {2}: {0}, on thread {1}.", Item, threadIndex, ItemIndex)
			ItemIndex = ItemIndex + 1
		Next

		ItemIndex = 0

    For Each Item As Integer In List2
			Console.WriteLine("List2 Repeat #1 value {2}: {0}, on thread {1}.", Item, threadIndex, ItemIndex)
			ItemIndex = ItemIndex + 1
		Next

		Console.WriteLine("Thread {0} finished...", threadIndex)
		Interlocked.Decrement(IsBusy)
	End Sub

	Public Sub FunctionToRunInMultipleThreads1(threadContext As Object)
		Dim ThreadIndex As Integer = CInt(threadContext)
		Console.WriteLine("thread {0} started...", ThreadIndex)

		Using ReadLock1 As IDisposable = Lock.GetReadLock()
			' Iterate through List1
			For Index As Integer = 0 To List1.Count - 1
				List1(Index) += Index
			Next

			' Upgrade read Lock1 to write Lock1.  Yes.  It is that simple.
			Using WriteLock1 As IDisposable = Lock1.GetWriteLock()
				For Index As Integer = 0 To List1.Count - 1
					List1.Add(List1(Index))
				Next
			End Using
		End Using

		Using WriteLock1 As IDisposable = Lock1.GetWriteLock()
			' Read Lock1 not needed.  But it shows Lock1ing in this order is OK.
			Using ReadLock1 As IDisposable = Lock1.GetReadLock()
				' Remove all but the first 10 records.
				List1.RemoveRange(10, List1.Count - 10)

				' Iterate through List1
				For Index As Integer = 0 To List1.Count - 1
					Console.WriteLine("List1 value {2}: {0}, on thread {1}.", List1(Index), ThreadIndex, Index)
				Next
			End Using
		End Using

		Dim ItemIndex As Integer = 0

    For Each Item As Integer In List2
			List2(ItemIndex) = List2(ItemIndex) + 1

			Console.WriteLine("List2 #2 value {2}: {0}, on thread {1}.", Item, threadIndex, ItemIndex)
			ItemIndex = ItemIndex + 1
		Next

		ItemIndex = 0

    For Each Item As Integer In List2
			Console.WriteLine("List2 Repeat #2 value {2}: {0}, on thread {1}.", Item, threadIndex, ItemIndex)
			ItemIndex = ItemIndex + 1
		Next

		Console.WriteLine("Thread {0} finished...", ThreadIndex)
		InterLocked.Decrement(IsBusy)
	End Sub
End Module
